#include<iostream>
#include<unistd.h>
#include<assert.h>
#include<cstring>
#include<cstdio>
#include<sys/types.h>
#include<sys/wait.h>

using namespace std;

//为什么不定义全局buffer来进行通信呢？因为有写时拷贝的存在，无法更改通信！

int main()
{
    //1.创建管道
    int pipefd[2] = {0}; //pipefd[0]:(嘴巴，读书)读端， pipefd[1]:(钢笔，写字)写端
    //On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.
    int n = pipe(pipefd);
    assert(n != -1);
    (void)n;

#ifdef DEBUG
    cout << "pipefd[0]:" << pipefd[0] << endl;
    cout << "pipefd[1]:" << pipefd[1] << endl;
#endif

    //2.创建子进程
    pid_t id = fork();
    assert(id != -1);
    if(id == 0)
    {
        //子进程--读
        //3.构建单向通信的通道，父进程写入，子进程读取(关闭写)
        //3.1关闭子进程不需要的fd
        close(pipefd[1]);
        char buffer[1024*8];
        while(true)
        {
            //sleep(20);
            //写入的一方，fd没有关闭，如果有数据，就读，没有数据就等
            //写入的一方，fd关闭，读取的一方，read会返回0，表示读到了文件的结尾！
            size_t s = read(pipefd[0],buffer,sizeof(buffer)-1);
            if(s > 0)
            {
                buffer[s] = 0;
                cout << "child get a message[" << getpid() << "] Father# " << buffer << endl;
            }
            else if(s == 0)
            {
                cout << "writer quit(father),me quit" << endl;
                break;
            }
        } 
        exit(0);
    }
    else
    {
        //父进程--写
        //3.构建单向通信的通道，父进程写入，子进程读取(关闭读)
        //3.1关闭子进程不需要的fd
        close(pipefd[0]);
        string message = "我是父进程，我正在给你发消息";
        int count = 0;
        char send_buffer[1024*8];
        while(true)
        {
            //3.2构建一个变化的字符串
            snprintf(send_buffer,sizeof(send_buffer), "%s[%d] : %d", message.c_str(),getpid(),count++);
            //3.3写入
            write(pipefd[1],send_buffer,strlen(send_buffer));
            //3.4 故意sleep
            sleep(1);
            cout << count << endl;
            if(count == 3) 
            {
                cout << "writer quit(father)" << endl;
                break;
            }
        }
        close(pipefd[1]);
    }
    pid_t ret = waitpid(id,nullptr,0);
    assert(ret > 0);
    (void)ret;

    return 0;
}